package com.newcrm.webapi;

import com.newcrm.bean.ExtInfo;
import com.newcrm.db.CompanyExtManager;
import com.newcrm.db.ConnectionManager;
import com.newcrm.db.CustomerCategoryManager;
import com.newcrm.db.CustomerFieldManager;
import com.newcrm.db.CustomerManager;
import com.newcrm.db.GroupManager;
import com.newcrm.exception.CustomerIsExistException;
import com.newcrm.exception.DBException;
import com.newcrm.thread.LuceneThread;
import com.newcrm.util.MD5;
import com.newcrm.util.ParameterUtil;
import com.newcrm.util.Util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;

public class OpenAPIServlet extends HttpServlet
{
    private static final long serialVersionUID = 6197488097691327491L;
    private static Logger logger = Logger.getLogger(OpenAPIServlet.class
            .getName());

    private Map<String, Integer> systemExtInfo = new HashMap();
    private Map<String, Integer> definedPeopleExtInfo = new HashMap();
    private Map<String, Integer> definedCompanyExtInfo = new HashMap();
    private Map<String, Integer> customerCategoryInfo = new HashMap();
    private Map<String, Integer> groupInfo = new HashMap();
    private int companyId = 1;

    public OpenAPIServlet()
    {
        this.systemExtInfo.put("phone",
                Integer.valueOf(1));
        this.systemExtInfo.put("email",
                Integer.valueOf(2));
        this.systemExtInfo.put("im",
                Integer.valueOf(3));
        this.systemExtInfo.put("website",
                Integer.valueOf(4));
        this.systemExtInfo.put("weibo",
                Integer.valueOf(5));
        this.systemExtInfo.put("address",
                Integer.valueOf(6));

        CustomerFieldManager customerFieldManager = new CustomerFieldManager();
        try {
            List result = customerFieldManager
                    .listAll(this.companyId);
            for (Object mapO : result) {
                Map map = (Map) mapO;
                switch (((Integer) map.get("FieldType")).intValue()) {
                    case 1:
                        this.definedCompanyExtInfo.put(
                                (String) map.get("CustomerFieldName"),
                                (Integer) map.get("CustomerFieldId"));
                        break;
                    case 2:
                        this.definedPeopleExtInfo.put(
                                (String) map.get("CustomerFieldName"),
                                (Integer) map.get("CustomerFieldId"));
                        break;
                    case 0:
                        this.definedCompanyExtInfo.put(
                                (String) map.get("CustomerFieldName"),
                                (Integer) map.get("CustomerFieldId"));
                        this.definedPeopleExtInfo.put(
                                (String) map.get("CustomerFieldName"),
                                (Integer) map.get("CustomerFieldId"));
                        break;
                    default:
                        logger.warn("filed type error");
                }
            }
        }
        catch (Exception ex)
        {
            logger.warn(
                    "Inital definedCompanyExtInfo or definedPeopleExtInfo failed ",
                    ex);
        }

        CustomerCategoryManager customerCategoryManager = new CustomerCategoryManager();
        try {
            List result = customerCategoryManager.list(
                    this.companyId, 1);
            for (Object mapO : result) {
                Map map = (Map) mapO;
                this.customerCategoryInfo.put((String) map.get("CategoryName"),
                        (Integer) map.get("CategoryId"));
            }
        }
        catch (Exception ex) {
            logger.warn("Inital customerCategoryInfo failed ", ex);
        }

        GroupManager groupManager = new GroupManager();
        try {
            List result = groupManager.list(this.companyId);
                for (Object mapO : result) {
                    Map map = (Map) mapO;
                    this.groupInfo.put((String) map.get("GroupName"),
                            (Integer) map.get("GroupId"));
                }
        }
        catch (Exception ex) {
            logger.warn("Inital groupInfo failed ", ex);
        }
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        JSONObject jsonObject = new JSONObject();

        String url = request.getRequestURI();
        String[] param = ParameterUtil.getParameters(url, "/openAPI");
        if (param == null) {
            logger.warn("param is null");
            jsonObject.put("error", "1");
            jsonObject.put("message", "param is null");
            out.println(jsonObject);
            out.flush();
            out.close();
            return;
        }

        String sign = request.getParameter("sign");

        if ((sign == null) || (sign.trim().length() == 0)) {
            logger.warn("sign is null");
            jsonObject.put("error", "1");
            jsonObject.put("message", "sign is null");
            out.println(jsonObject);
            out.flush();
            out.close();
            return;
        }

        String timestamp = request.getParameter("timestamp");
        if ((timestamp == null) || (timestamp.trim().length() == 0)) {
            logger.warn("timestamp is null");
            jsonObject.put("error", "1");
            jsonObject.put("message", "timestamp is null");
            out.println(jsonObject);
            out.flush();
            out.close();
            return;
        }
        Date time = Util.str2Date3(timestamp);
        if (time == null) {
            logger.warn("time which converted from timestamp is null.");
            jsonObject.put("error", "1");
            jsonObject.put("message",
                    "time which converted from timestamp is null.");
            out.println(jsonObject);
            out.flush();
            out.close();
            return;
        }
        Date now = new Date();
        long step = now.getTime() - time.getTime();

        if (step > 300000L) {
            logger.warn("调用时间和系统时间戳相差超过5分钟，请检查系统时间！");
            jsonObject.put("error", "1");
            jsonObject.put("message", "调用时间和系统时间戳相差超过5分钟，请检查系统时间！");
            out.println(jsonObject);
            out.flush();
            out.close();
            return;
        }

        CompanyExtManager manager = new CompanyExtManager();
        String token = manager.getFieldValue(this.companyId,
                19);

        if (!sign.equals(MD5.getMD5(token + timestamp)))
        {
            logger.warn("签名不正确，请与系统管理员核对token值是否一致！");
            jsonObject.put("error", "1");
            jsonObject.put("message", "签名不正确，请与系统管理员核对token值是否一致！");
            out.println(jsonObject);
            out.flush();
            out.close();
            return;
        }

        if (param.length == 2) {
            if (("customer".equals(param[0])) && ("new".equals(param[1]))) {
                int[] customerIds = addCustomer(request, response);
                if ((customerIds == null) || (customerIds.length == 0)) {
                    logger.warn("添加客户失败, customerIds is null or length is 0");
                    jsonObject.put("error", "1");
                    jsonObject.put("message", "添加客户失败，数据格式不正确");
                    out.println(jsonObject);
                    out.flush();
                    out.close();
                    return;
                }

                if (customerIds[0] == -1) {
                    logger.warn("添加单独联系人成功， 单独联系人ID：" + customerIds[1]);
                    jsonObject.put("error", "0");
                    jsonObject.put("customerId", Integer.valueOf(customerIds[1]));
                    jsonObject.put("message", "添加单独联系人成功");
                } else if (customerIds[0] == 0) {
                    logger.warn("添加客户重复， 重复客户ID：" + customerIds[1]);
                    jsonObject.put("error", "2");
                    jsonObject.put("customerId", Integer.valueOf(customerIds[1]));
                    jsonObject.put("message", "添加客户重复");
                } else {
                    logger.warn("添加客户成功， 客户ID：" + customerIds[0]);
                    jsonObject.put("error", "0");
                    jsonObject.put("customerId", Integer.valueOf(customerIds[0]));
                    jsonObject.put("message", "添加客户成功");
                }
                logger.warn("customerIds is" + customerIds[0] + "size " +
                        customerIds.length);
            } else if (("customer".equals(param[0])) && ("query".equals(param[1]))) {
                List result = queryCustomer(request,
                        response);
                if (result == null) {
                    jsonObject.put("error", "1");
                    jsonObject.put("message", "查询失败或者没有结果，请检查条件重新查询");
                    out.println(jsonObject);
                    out.flush();
                    out.close();
                    return;
                }

                logger.warn("result is" + result.size());
                jsonObject.put("error", "0");
                jsonObject.put("message", "查询成功");
                jsonObject.put("result", result);
            }
        }

        out.println(jsonObject);
        out.flush();
        out.close();
    }

    private int[] addCustomer(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        String body = getJSONString(request);
        if ((body == null) || (body.trim().length() == 0)) {
            logger.warn("json body is null");
            return null;
        }

        String companyName = "";
        int categoryId = 0;
        String peopleName = "";
        String companyNote = "";
        String operationUserId = "";
        int visible = 1;
        String title = "";
        String permissionId = "";
        List companyExtInfos = new ArrayList();
        List peopleExtInfos = new ArrayList();
        int[] customerIds = new int[1];
        try
        {
            JSONObject json = JSONObject.fromObject(body);
            companyName = Util.getJSONStringValue(json, "companyName");

            if ((companyName == null) || (companyName.trim().length() == 0)) {
                categoryId = -1;
            }
            else if (this.customerCategoryInfo.containsKey(
                    Util.getJSONStringValue(json, "categoryId")))
            {
                categoryId = ((Integer)this.customerCategoryInfo.get(Util.getJSONStringValue(
                        json, "categoryId"))).intValue();
            }

            peopleName = Util.getJSONStringValue(json, "peopleName");
            companyNote = Util.getJSONStringValue(json, "companyNote");
            operationUserId = Util.getJSONStringValue(json, "operationUserId");
            title = Util.getJSONStringValue(json, "title");

            if ("个人数据".equals(Util.getJSONStringValue(json, "visible"))) {
                visible = 4;
                permissionId = Util.getJSONStringValue(json, "permissionId");
            } else {
                visible = 1;

                if (this.groupInfo.containsKey(Util.getJSONStringValue(json,
                        "permissionId"))) {
                    permissionId = ((Integer)this.groupInfo.get(
                            Util.getJSONStringValue(json, "permissionId")))
                            .toString();
                }

            }

            if (json.has("companyExtInfos")) {
                JSONArray extInfos = json.getJSONArray("companyExtInfos");
                for (int i = 0; i < extInfos.size(); i++) {
                    ExtInfo extInfo = new ExtInfo();
                    JSONObject item = extInfos.getJSONObject(i);
                    String key = Util.getJSONStringValue(item, "key");
                    if (this.systemExtInfo.containsKey(key)) {
                        extInfo.type = ((Integer)this.systemExtInfo.get(key)).intValue();
                        extInfo.info1 = Util.getJSONStringValue(item, "value");
                        companyExtInfos.add(extInfo); } else {
                        if (!this.definedCompanyExtInfo.containsKey(key)) continue;
                        extInfo.type = ((Integer)this.definedCompanyExtInfo.get(key)).intValue();
                        extInfo.info1 = Util.getJSONStringValue(item, "value");
                        companyExtInfos.add(extInfo);
                    }

                    logger.warn("add companyExtInfos key is " + extInfo.type +
                            "and value is " + extInfo.info1);
                    logger.warn("json companyExtInfos key is " +
                            Util.getJSONStringValue(item, "key") +
                            " value is " +
                            Util.getJSONStringValue(item, "value"));
                }

            }

            if (json.has("peopleExtInfos")) {
                JSONArray extInfos = json.getJSONArray("peopleExtInfos");
                for (int i = 0; i < extInfos.size(); i++) {
                    ExtInfo extInfo = new ExtInfo();
                    JSONObject item = extInfos.getJSONObject(i);
                    String key = Util.getJSONStringValue(item, "key");
                    if (this.systemExtInfo.containsKey(key)) {
                        extInfo.type = ((Integer)this.systemExtInfo.get(key)).intValue();
                        extInfo.info1 = Util.getJSONStringValue(item, "value");
                        peopleExtInfos.add(extInfo); } else {
                        if (!this.definedPeopleExtInfo.containsKey(key)) continue;
                        extInfo.type = ((Integer)this.definedPeopleExtInfo.get(key)).intValue();
                        extInfo.info1 = Util.getJSONStringValue(item, "value");
                        peopleExtInfos.add(extInfo);
                    }

                    logger.warn("add peopleExtInfos key is " + extInfo.type +
                            "and value is " + extInfo.info1);
                    logger.warn("json companyExtInfos key is " +
                            Util.getJSONStringValue(item, "key") +
                            " value is " +
                            Util.getJSONStringValue(item, "value"));
                }
            }

            logger.warn("json companyName is " + companyName);
            logger.warn("json categoryId is " + categoryId);
            logger.warn("json peopleName is " + peopleName);
            logger.warn("json visible is " + visible);
            logger.warn("json title is " + title);
            logger.warn("json permissionId is " + permissionId);

            CustomerManager manager = new CustomerManager();

            Connection conn = ConnectionManager.getInstance().getConnection();
            if (conn != null)
                try {
                    customerIds = manager.importCustomer(conn, companyName,
                            categoryId, peopleName, title, companyNote,
                            companyExtInfos, peopleExtInfos, operationUserId,
                            this.companyId, visible, permissionId, true, 1);
                    if (customerIds == null)
                        logger.warn("add customer failed ");
                    else
                        logger.warn("add customer success, customerId: " +
                                customerIds[0]);
                }
                catch (DBException e) {
                    logger.warn("add customer failed ", e);
                    return null;
                } catch (CustomerIsExistException e) {
                    logger.warn("add customer exist " + e.getCustomerId());
                    return new int[] { 0, e.getCustomerId() };
                }
        }
        catch (JSONException e)
        {
            logger.warn("get json object failed, json:" + body, e);
            return null;
        }

        String indexPath = getServletConfig().getServletContext()
                .getRealPath("lucene/");
        new LuceneThread(indexPath, false).start();

        logger.warn("body:" + body);
        return customerIds;
    }

    private List<Map<String, Object>> queryCustomer(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        String body = getJSONString(request);

        if ((body == null) || (body.trim().length() == 0)) {
            logger.warn("json body is null");
            return null;
        }

        String companyName = "";
        String queryId = "";
        String phone = "";
        String im = "";
        String email = "";
        String website = "";
        List result = null;
        try
        {
            JSONObject json = JSONObject.fromObject(body);
            companyName = Util.getJSONStringValue(json, "companyName");
            queryId = Util.getJSONStringValue(json, "queryId");
            phone = Util.getJSONStringValue(json, "phone");
            im = Util.getJSONStringValue(json, "im");
            email = Util.getJSONStringValue(json, "email");
            website = Util.getJSONStringValue(json, "website");

            logger.warn("json companyName is " + companyName);
            logger.warn("json queryId is " + queryId);
            logger.warn("json phone is " + phone);
            logger.warn("json im is " + im);
            logger.warn("json email is " + email);
            logger.warn("json website is " + website);

            if (((companyName == null) || (companyName.trim().length() == 0)) &&
                    ((queryId == null) || (queryId.trim().length() == 0)) &&
                    ((phone == null) || (phone.trim().length() == 0)) &&
                    ((im == null) || (im.trim().length() == 0)) &&
                    ((email == null) || (email.trim().length() == 0)) && (
                    (website == null) || (website.trim().length() == 0))) {
                return null;
            }

            CustomerManager manager = new CustomerManager();
            try {
                result = manager.queryOpenAPICustomer(companyName, queryId,
                        phone, im, email, website);
                if (result == null) {
                    logger.warn("query customer failed ");
                    return null;
                }
            }
            catch (DBException e) {
                logger.warn("query customer failed ", e);
                return null;
            } catch (SQLException e) {
                logger.warn("query customer failed ", e);
                return null;
            }
        } catch (JSONException e) {
            logger.warn("get json object failed, json: " + body, e);
            return null;
        }

        return result;
    }

    private String getJSONString(HttpServletRequest request)
    {
        StringBuffer body = new StringBuffer();
        String line = null;
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    request.getInputStream(), "UTF-8"));

            while ((line = reader.readLine()) != null) {
                body.append(line);
            }

            return body.toString();
        } catch (Exception e) {
            logger.warn("get json string failed", e);
        }

        return null;
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        doGet(request, response);
    }
}